﻿using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Media;

using Syngine.Components;

namespace Syngine.Audio
{
	/// <summary>
	/// 
	/// </summary>
	public class AudioManager : Playable, IAudioManager
	{
		#region Fields

		private Song _currentSong;

		#endregion

		#region Constructors

		

		#endregion

		#region Properties

		/// <summary>
		/// Gets or sets a value indicating whether this <see cref="AudioManager"/> is on repeat.
		/// </summary>
		/// <value>
		///   <c>true</c> if repeat; otherwise, <c>false</c>.
		/// </value>
		public bool Repeat
		{
			get
			{
				return MediaPlayer.IsRepeating;
			}
			set
			{
				MediaPlayer.IsRepeating = value;
			}
		}

		/// <summary>
		/// Gets or sets a value indicating whether this <see cref="AudioManager"/> is muted.
		/// </summary>
		/// <value>
		///   <c>true</c> if muted; otherwise, <c>false</c>.
		/// </value>
		public bool Muted
		{
			get
			{
				return MediaPlayer.IsMuted;
			}
			set
			{
				MediaPlayer.IsMuted = value;
			}
		}

		/// <summary>
		/// Gets or sets the volume.
		/// </summary>
		/// <value>
		/// The volume.
		/// </value>
		public float Volume
		{
			get
			{
				return MediaPlayer.Volume;
			}
			set
			{
				if (value < 0)
				{
					MediaPlayer.Volume = 0;
				}
				else if (value > 1)
				{
					MediaPlayer.Volume = 1;
				}
				else
				{
					MediaPlayer.Volume = value;
				}
			}
		}

		#endregion

		#region Methods

		public override void Pause()
		{
			if (!Muted && MediaPlayer.State == MediaState.Playing)
			{
				MediaPlayer.Pause();

				base.Pause();
			}
		}

		/// <summary>
		/// Pauses the specified song.
		/// </summary>
		/// <param name="song">The song.</param>
		public void Pause(Song song)
		{
			if (_currentSong == song && MediaPlayer.State == MediaState.Playing)
			{
				MediaPlayer.Pause();
			}

			base.Pause();
		}

		public override void Stop()
		{
			if ((MediaPlayer.State == MediaState.Paused || MediaPlayer.State == MediaState.Playing))
			{
				MediaPlayer.Stop();

				base.Stop();
			}
		}

		public override void Play()
		{
			if ((MediaPlayer.State == MediaState.Paused || MediaPlayer.State == MediaState.Stopped))
			{
				if (_currentSong != null)
				{
					MediaPlayer.Play(_currentSong);

					base.Play();
				}
			}
		}

		/// <summary>
		/// Plays the specified song.
		/// </summary>
		/// <param name="song">The song.</param>
		public virtual void Play(Song song)
		{
			if ((MediaPlayer.State == MediaState.Paused || MediaPlayer.State == MediaState.Stopped))
			{
				MediaPlayer.Play(_currentSong = song);
				
				base.Play();
			}
		}

		/// <summary>
		/// Plays the song.
		/// </summary>
		/// <param name="asset">The asset.</param>
		public void PlaySong(string asset)
		{
			Play(GameContext.Game.Content.Load<Song>(asset));
		}

		/// <summary>
		/// Plays the specified sound.
		/// </summary>
		/// <param name="sound">The sound.</param>
		public void Play(SoundEffect sound)
		{
			Play(sound, Volume);
		}

		/// <summary>
		/// Plays the specified sound.
		/// </summary>
		/// <param name="sound">The sound.</param>
		/// <param name="volume">The volume.</param>
		public void Play(SoundEffect sound, float volume)
		{
			Play(sound, volume, 0.0f, 0.0f);
		}

		/// <summary>
		/// Plays the specified sound.
		/// </summary>
		/// <param name="sound">The sound.</param>
		/// <param name="volume">The volume.</param>
		/// <param name="pitch">The pitch.</param>
		public void Play(SoundEffect sound, float volume, float pitch)
		{
			Play(sound, volume, pitch, 0.0f);
		}

		/// <summary>
		/// Plays the specified sound.
		/// </summary>
		/// <param name="sound">The sound.</param>
		/// <param name="volume">The volume.</param>
		/// <param name="pitch">The pitch.</param>
		/// <param name="pan">The pan.</param>
		public void Play(SoundEffect sound, float volume, float pitch, float pan)
		{
			sound.Play(volume, pitch, pan);
			base.Play();
		}

		/// <summary>
		/// Plays the sound.
		/// </summary>
		/// <param name="asset">The asset.</param>
		public void PlaySound(string asset)
		{
			Play(GameContext.Game.Content.Load<SoundEffect>(asset));
		}

		/// <summary>
		/// Plays the sound.
		/// </summary>
		/// <param name="asset">The asset.</param>
		/// <param name="volume">The volume.</param>
		public void PlaySound(string asset, float volume)
		{
			Play(GameContext.Game.Content.Load<SoundEffect>(asset), volume);
		}

		/// <summary>
		/// Plays the sound.
		/// </summary>
		/// <param name="asset">The asset.</param>
		/// <param name="volume">The volume.</param>
		/// <param name="pitch">The pitch.</param>
		public void PlaySound(string asset, float volume, float pitch)
		{
			Play(GameContext.Game.Content.Load<SoundEffect>(asset), volume, pitch);
		}

		/// <summary>
		/// Plays the sound.
		/// </summary>
		/// <param name="asset">The asset.</param>
		/// <param name="volume">The volume.</param>
		/// <param name="pitch">The pitch.</param>
		/// <param name="pan">The pan.</param>
		public void PlaySound(string asset, float volume, float pitch, float pan)
		{
			Play(GameContext.Game.Content.Load<SoundEffect>(asset), volume, pitch, pan);
			base.Play();
		}

		#endregion
	}
}